package net.chasing.androidbaseconfig.util;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.text.TextUtils;
import android.util.Base64;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.webkit.CookieManager;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.FrameLayout;

import androidx.core.content.ContextCompat;

import net.chasing.androidbaseconfig.R;
import net.chasing.androidbaseconfig.util.thread.ThreadPoolUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

/**
 * Created by chasing on 2021/4/21.
 */
public class WebViewUtils {
    private final FrameLayout.LayoutParams COVER_SCREEN_PARAMS = new FrameLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    private View customView;
    private FrameLayout fullscreenContainer;
    private WebChromeClient.CustomViewCallback customViewCallback;

    public WebViewUtils() {

    }

    // region 静态公共方法
    @SuppressLint("SetJavaScriptEnabled")
    public static void initSetting(Context context, WebView webView) {
        if (webView == null) return;
        // 部分机型存在背景颜色为黑色的情况，进行设置为透明
        webView.setBackgroundColor(ContextCompat.getColor(context, R.color.transparent));

        webView.requestFocus();//如果不设置，则在点击网页文本输入框时，不能弹出软键盘及不响应其他的一些事件
//        mContentWv.setInitialScale(1); //设置页面加载比例，1代表直接将整个网页加载到界面上，会自动缩放进行适应到屏幕尺寸
        WebSettings webSettings = webView.getSettings();
//        webSettings.setTextZoom(100);//设置WebView中加载页面字体变焦百分比，默认100。//嵌入一个H5页面，使H5页面的字体不会随用户自己调整的系统字体变化而变化
        webSettings.setJavaScriptEnabled(true);
        webSettings.setDomStorageEnabled(true);
        webSettings.setDefaultTextEncodingName("UTF-8");
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        webSettings.setBlockNetworkImage(false);//解决图片不显示
        webSettings.setLoadsImagesAutomatically(true);
        // 根据 HTTP 协议头里的 Cache-Control（或 Expires）和 Last-Modified（或 Etag）等字段来控制文件缓存的机制，
        // 现在设置的缓存方式是根据网页设置的这几个值判断的，没有过期的话就会读取本地缓存，过期了则进行重新加载
        // 本地缓存在内存不足的时候也会被清理，在网络请求失败的时候显示错误页面
        webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
        webSettings.setUseWideViewPort(true);// 这个很关键，设置webview推荐使用的窗口
        webSettings.setLoadWithOverviewMode(true); // 设置webview加载的页面的模式，也设置为true
        webSettings.setDisplayZoomControls(false); // 隐藏webview缩放按钮
        webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);//解决字符串换行问题
        webSettings.setMediaPlaybackRequiresUserGesture(false);
        webSettings.setBuiltInZoomControls(false);//关闭缩放功能support zoom
        webSettings.setSupportZoom(false);
        webSettings.setAllowUniversalAccessFromFileURLs(true);
        webSettings.setAllowFileAccess(true);
        webSettings.setAllowFileAccessFromFileURLs(true);

        //允许混合加载，即http与https可以同时加载，避免加载的是https的url，而里面的图片视频使用的是http的情况
        webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);

        WebView.setWebContentsDebuggingEnabled(true);

        String version = webSettings.getUserAgentString();
        L.i("QbSdk original version: " + version);
    }

    public static void destroy(WebView webView) {
        if (webView == null) return;
        ViewParent parent = webView.getParent();
        if (parent instanceof ViewGroup)
            ((ViewGroup) parent).removeView(webView);

        webView.stopLoading();
        // 退出时调用此方法，移除绑定的服务，否则某些特定系统会报错
        webView.getSettings().setJavaScriptEnabled(false);
        webView.clearHistory();
        webView.removeAllViews();
        webView.destroy();
    }

    //清除WebView的cookies数据.防止下一个登录用户还是传递上一个用户的cookies记录造成网页中信息紊乱。
    public static void clearWebViewCookies() {
        CookieManager cookieManager = CookieManager.getInstance();
        //清除cookie
        cookieManager.removeSessionCookies(null);
        cookieManager.removeAllCookies(null);
    }

    //注意：文件的生成格式不同，需要用不同的格式去读取
    public static void loadLocalProtocolUTF_8(Context context, WebView webView, int rawResId) {
        try {
            InputStream is = context.getResources().openRawResource(rawResId);
            InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
            BufferedReader br = new BufferedReader(isr);
            StringBuilder sb = new StringBuilder();
            String str;
            while ((str = br.readLine()) != null) {
                sb.append(str);
            }
            String content = getDefaultWebViewStyle(sb.toString());
            content = Base64.encodeToString(content.getBytes(), Base64.NO_PADDING);
            webView.loadData(content, "text/html; charset=UTF-8", "base64");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //注意：文件的生成格式不同，需要用不同的格式去读取
    public static void loadLocalProtocol(Context context, WebView webView, int rawResId) {
        try {
            InputStream is = context.getResources().openRawResource(rawResId);
            InputStreamReader isr = new InputStreamReader(is, "GBK");
            BufferedReader br = new BufferedReader(isr);
            StringBuilder sb = new StringBuilder();
            String str;
            while ((str = br.readLine()) != null) {
                sb.append(str);
            }
            String content = getDefaultWebViewStyle(sb.toString());
            content = Base64.encodeToString(content.getBytes(), Base64.NO_PADDING);
            webView.loadData(content, "text/html; charset=UTF-8", "base64");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static String getDefaultWebViewStyle(String displayContent) {
        return "<!DOCTYPE html>" +
                "<html>" +
                "<head>" +
                "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />" +
                "<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge, chrome=1\" />" +
                "<meta name=\"renderer\" content=\"webkit|ie-comp|ie-stand\">" +
                "<meta name=\"viewport\" content=\"initial-scale=1,width=device-width,user-scalable=no\" />" +
                "<meta charset=\"utf-8\" />" +
                "<style>img{max-width:100%}</style>" +
                "</head>" +
                "<body style='margin:0;padding:0'>" +
                displayContent +
                "</body>" +
                "</html>";
    }

    /**
     * 调用js方法（注意：必须在主线程上进行调用）
     * 单个参数的时候添加单引号（添加和不添加对于网页端JS来说是不一样的）
     * 4.4开始，使用evaluateJavascript，效率比使用loadUrl高
     */
    public static void evaluateJavascript(WebView webView, String methodName, String... params){
        evaluateJavascript(webView, null, methodName, params);
    }

    public static void evaluateJavascript(WebView webView, ValueCallback<String> callback, String methodName, String... params) {
        if (webView == null || methodName == null) return;
        StringBuilder sb = new StringBuilder();
        if (params != null) {
            if (params.length == 1) {
                if (!TextUtils.isEmpty(params[0]))
//                    sb.append("'").append(params[0]).append("'");
                    sb.append("`").append(params[0]).append("`");
            } else if (params.length > 1) {
                for (String param : params) {
                    if (!TextUtils.isEmpty(param))
//                        sb.append("'").append(param).append("'").append(',');
                        sb.append("`").append(param).append("`").append(',');
                }
                if (sb.length() > 0 && sb.lastIndexOf(",") != -1)
                    sb.deleteCharAt(sb.lastIndexOf(","));
            }
        }
        String jsFunction = String.format("javascript:%s(%s)", methodName, sb);
        ThreadPoolUtils.getInstance().executeOnMainThread(() ->
                webView.evaluateJavascript(jsFunction, callback));
    }
    // endregion

    /**
     * 视频播放全屏
     **/
    public void showCustomView(Activity activity, View view, WebChromeClient.CustomViewCallback callback) {
        // if a view already exists then immediately terminate the new one
        if (activity != null) {
            if (customView != null) {
                callback.onCustomViewHidden();
                return;
            }
            activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            FrameLayout decor = (FrameLayout) activity.getWindow().getDecorView();
            fullscreenContainer = new FullscreenHolder(activity);
            fullscreenContainer.addView(view, COVER_SCREEN_PARAMS);
            decor.addView(fullscreenContainer, COVER_SCREEN_PARAMS);
            customView = view;
            StatusBarUtil.setStatusBarVisibility(activity, false);
            customViewCallback = callback;
        }
    }

    /**
     * 隐藏视频全屏
     */
    public boolean hideCustomView(Activity activity) {
        if (activity == null || customView == null) {
            return false;
        }

        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        StatusBarUtil.setStatusBarVisibility(activity, true);
        FrameLayout decor = (FrameLayout) activity.getWindow().getDecorView();
        decor.removeView(fullscreenContainer);
        fullscreenContainer = null;
        customView = null;
        if (customViewCallback != null)
            customViewCallback.onCustomViewHidden();
        customViewCallback = null;
        return true;
    }

    /**
     * 全屏容器界面
     */
    public static class FullscreenHolder extends FrameLayout {
        public FullscreenHolder(Context ctx) {
            super(ctx);
            setBackgroundColor(ctx.getResources().getColor(android.R.color.black));
        }

        @SuppressLint("ClickableViewAccessibility")
        @Override
        public boolean onTouchEvent(MotionEvent evt) {
            return true;
        }
    }
}
